<template>
    <div class="flex flex-col gap-5 w-full">
        <div class="input-wrapper">
            <div v-if="filesList.length > 0" class="files">
                <div v-for="(item, index) in filesList" :key="index" class="file-box">
                    <div class="shrink-0 flex items-center text-center w-[35px] h-[35px] rounded-md bg-lighter">
                        <el-image
                            v-if="item.url && getFileType(item.raw) === 'file'"
                            :src="suffixUtil.findUnitIcon(item.name)"
                            :hide-on-click-modal="true"
                            class="w-full h-full rounded-md"
                        />

                        <el-image
                            v-else-if="item.url"
                            :src="item.url"
                            :preview-src-list="item.url ? [item.url] : []"
                            :hide-on-click-modal="true"
                            class="w-full h-full rounded-md"
                        />
                    </div>
                    <div>
                        <p class="text-tx-regular line-clamp-1 mb-1">{{ item.name }}</p>
                        <p class="text-tx-secondary">
                            {{ (item.response as any)?.data.ext.toUpperCase() }}
                            {{ toolsUtil.formatBytes(item.size) }}
                        </p>
                    </div>
                    <icon
                        class="close"
                        name="el-icon-CircleCloseFilled"
                        :size="16"
                        @click="handleFileDel(index)"
                    />
                </div>
            </div>

            <div>
                <el-input
                    v-model="question"
                    :autosize="{ minRows: 2, maxRows: 20 }"
                    placeholder="请输入问题（Shift + Enter）= 换行"
                    type="textarea"
                    resize="none"
                    :disabled="disabled"
                    @compositionstart="isInputEnter = true"
                    @compositionend="isInputEnter = false"
                    @keydown="handleInputEnter"
                />

                <div class="flex items-center justify-between">
                    <div v-if="isWebSearch" class="flex items-center">
                        <div
                            class="tool-button"
                            :class="isSearchOpen ? 'active' : ''"
                            @click="handleSearch"
                        >
                            <icon name="svg-icon-WebSearch" :size="14" />
                            <span>联网搜索</span>
                        </div>
                    </div>
                    <div v-else></div>

                    <div class="flex items-center gap-3">
                        <div
                            v-if="maxUploadNum && (isUploadFiles || isUploadImage)"
                            class="flex items-center"
                        >
                            <el-upload
                                v-model:file-list="filesList"
                                class="flex items-center"
                                :accept="uploadAccept"
                                :limit="maxUploadNum"
                                :action="uploadParams.action"
                                :headers="uploadParams.header"
                                :show-file-list="false"
                                :multiple="false"
                                :disabled="disabled"
                                :on-success="uploadSuccess"
                            >
                                <template #trigger>
                                    <el-tooltip :content="uploadTips">
                                        <icon name="el-icon-Link" :size="28" color="#999" />
                                    </el-tooltip>
                                </template>
                            </el-upload>
                        </div>

                        <div class="split-line"></div>

                        <el-button
                            class="sender"
                            type="primary"
                            size="default"
                            :loading="loading"
                            :disabled="loading || disabled || !question"
                            @click="handleSending"
                        >
                            <icon v-if="!loading" name="el-icon-Promotion" :size="16" />
                        </el-button>
                    </div>
                </div>
            </div>
        </div>

        <div class="input-keyword">
            <div
                v-for="(item, index) in instruct"
                :key="index"
                class="keyword-item"
                @click="question = item.content"
            >
                <photos v-if="item?.icon" :src="item?.icon" :width="16" :height="16" />
                <span>{{ item.name }}</span>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import type { UploadUserFile } from 'element-plus'
import toolsUtil from '~/utils/tools'
import suffixUtil from '~/utils/suffix'
import config from '~/config/index'
import useUserStore from '~/stores/user'

const props = withDefaults(
    defineProps<{
        // 接收中
        loading?: boolean;
        // 禁止输入
        disabled?: boolean;
        // 最大上传数量
        maxUploadNum?: number;
        // 支持上传文档
        isUploadFiles?: boolean;
        // 支持上传图片
        isUploadImage?: boolean;
        // 显示情况按钮
        isShowClear?: boolean;
        // 联网搜索按钮
        isWebSearch?: boolean;
        // 建议指令列表
        instruct?: any;
    }>(),
    {
        loading: false,
        disabled: false,
        maxUploadNum: 0,
        isUploadFiles: false,
        isUploadImage: false,
        isShowClear: false,
        isWebSearch: false,
        instruct: []
    }
)

const emits = defineEmits<{
    (
        event: 'sending',
        question: string,
        messages: any[],
        files: any[],
    ): void,
    (event: 'clear'): void
    (event: 'search', status: boolean): void
}>()

// 联网搜索
const isSearchOpen = ref<boolean>(false)
// 输入回车
const isInputEnter = ref<boolean>(false)
// 附件列表
const filesList = ref<UploadUserFile[]>([])
// 提问问题
const question = ref<string>('')
// 上传参数
const uploadParams = ref({
    action: `${config.baseUrl}/v1/files/upload`,
    header: {
        Authorization: `Bearer ${useUserStore().$state.token}`,
        Terminal: config.terminal
    }
})

// 上传扩展
const uploadAccept = computed(() => {
    if (props.isUploadFiles && props.isUploadImage) {
        return '.pdf,.doc,.docx,.xlsx,.ppt,pptx,.txt,.md,.jpg,.jpeg,.png'
    } else if (props.isUploadFiles) {
        return '.pdf,.doc,.docx,.xlsx,.ppt,.pptx,.txt,.md'
    } else if (props.isUploadImage) {
        return '.jpg,.jpeg,.png'
    }
    return ''
})

// 上传提示
const uploadTips = computed(() => {
    const num: number = props.maxUploadNum
    if (props.isUploadFiles && props.isUploadImage) {
        return '支持上传文件（最多' + num + '个）接受 pdf、docx、xlsx、ppt、txt、图片等'
    } else if (props.isUploadFiles) {
        return '支持上传文档（最多' + num + '个）接受 pdf、docx、xlsx、ppt、txt'
    } else if (props.isUploadImage) {
        return '支持上传图片（最多' + num + '个）接受 jpg、jpeg、png'
    }
    return ''
})

/**
 * 上传成功
 *
 * @param response
 * @param file
 * @author zero
 */
const uploadSuccess = (response: any, file: any) => {
    if (response.code === 0) {
        const index = filesList.value.indexOf(file)
        filesList.value[index].url = response.data.url
    } else {
        filesList.value.pop()
        feedback.msgError(response.msg)
    }
}

/**
 * 搜索开关
 */
const handleSearch = () => {
    isSearchOpen.value = !isSearchOpen.value
    emits('search', isSearchOpen.value)
}

/**
 * 删除文件
 *
 * @param index
 * @author zero
 */
const handleFileDel = (index: number) => {
    filesList.value.splice(index, 1)
}

/**
 * 回车发起对话
 *
 * @param e
 * @author zero
 */
const handleInputEnter = (e: any) => {
    if (e.shiftKey && e.keyCode === 13) {
        return
    }
    if (isInputEnter.value) {
        return
    }
    if (e.keyCode === 13) {
        handleSending()
        return e.preventDefault()
    }
}

/**
 * 处理发送请求
 */
const handleSending = () => {
    const attach: any = []
    const files: any = []

    filesList.value.forEach((item: any) => {
        if (item.response.code === 0) {
            const data = item.response.data
            attach.push({
                type: getFileType(item.raw),
                file_id: data.id,
                file_name: data.name,
                file_size: data.size,
                file_ext: data.ext,
                file_path: data.path
            })
            files.push({
                id: data.id,
                file_type: getFileType(item.raw),
                file_name: data.name,
                file_size: data.size,
                file_ext: data.ext,
                file_path: data.url
            })
        }
    })

    const messages = []
    if (attach.length > 0) {
        attach.push({type: 'text', text: question.value})
        messages.push({
            role: 'user',
            content: attach
        })
    } else {
        messages.push({
            role: 'user',
            content: question.value
        })
    }

    emits('sending', question.value, messages, files)
}

/**
 * 获取文件类型
 *
 * @param raw
 * @author zero
 */
const getFileType = (raw: any): string => {
    const type: string = raw.type.split('/')[1]
    if (['mp4'].includes(type)) {
        return 'video'
    } else if (['jpg', 'jpeg', 'png'].includes(type)) {
        return 'image'
    }
    return 'file'
}

/**
 * 设置输入内容
 */
const setInputValue = (value: string = '') => {
    question.value = value
    filesList.value = []
}

defineExpose({
    setInputValue
})
</script>

<style scoped lang="scss">
.input-wrapper {
    position: relative;
    flex: 1;
    width: 100%;
    padding: 10px;
    border: 1px solid var(--el-border-color-light);
    border-radius: 18px;
    :deep(.el-textarea.is-disabled) {
        .el-textarea__inner {
            background-color: unset;
        }
    }
    :deep(.el-textarea__inner) {
        height: 80px !important;
        min-height: 80px !important;
        box-shadow: none;
        &:focus,
        &:hover {
            box-shadow: none;
        }
    }

    .sender {
        width: 32px;
        height: 32px;
        padding: 0;
        border-radius: 50%;
        :deep(.el-icon.is-loading) {
            margin-right: -8px;
        }
    }

    .tool-button {
        display: flex;
        gap: 5px;
        align-items: center;
        padding: 10px 12px;
        line-height: 1;
        color: var(--el-text-color-regular);
        cursor: pointer;
        border: 1px solid var(--el-border-color-light);
        border-radius: 10px;
        &:hover {
            background-color: var(--el-bg-color-page);
        }
        &.active {
            color: var(--el-color-primary);
            background-color: var(--el-color-primary-light-9);
            border-color: var(--el-color-primary);
        }
    }

    .split-line {
        width: 1px;
        height: 19px;
        background: var(--el-bg-color-page);
    }

    .files {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        align-items: center;
        align-self: flex-start;
        width: 100%;
        margin-bottom: 10px;
        .file-box {
            position: relative;
            box-sizing: border-box;
            display: flex;
            gap: 10px;
            align-items: center;
            min-width: 180px;
            max-width: 250px;
            height: 52px;
            padding: 10px;
            font-size: 12px;
            background: var(--el-bg-color-page);
            border-radius: 8px;
            .close {
                position: absolute;
                top: -5px;
                right: -5px;
                display: flex;
                align-items: center;
                justify-content: center;
                color: var(--el-text-color-regular);
                &:hover {
                    color: var(--el-color-error);
                    cursor: pointer;
                }
            }
        }
    }
}

.input-keyword {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    padding: 0 10px;
    .keyword-item {
        display: flex;
        flex-wrap: nowrap;
        gap: 5px;
        align-items: center;
        width: max-content;
        padding: 11px 14px;
        line-height: 1;
        color: var(--el-text-color-regular);
        cursor: pointer;
        border: 1px solid var(--el-border-color-light);
        border-radius: 28px;
        &:hover {
            background-color: var(--el-bg-color-page);
        }
    }
}
</style>
